home *** CD-ROM | disk | FTP | other *** search
/ World of Video / World of Video.iso / gfxprograms / 3dprograms / t3dlib / source / writelwob.c < prev    next >
C/C++ Source or Header  |  1995-02-13  |  11KB  |  495 lines

  1. /* writelwob.c - write a LightWave3D object file
  2.  *             - by traversing the TTDDDLIB database
  3.  *             - written by Glenn M. Lewis - 8/7/92
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include "t3dlib.h"
  9. #ifdef __STDC__
  10. #include <stdlib.h>
  11. #include <strings.h>
  12. #include "writelwob_protos.h"
  13. #endif
  14.  
  15. #ifdef AZTEC_C
  16. #include <fcntl.h>
  17. #include <exec/types.h>
  18. #endif
  19.  
  20. static void process_INFO();
  21. static void process_OBJ();
  22. static void process_EXTR();
  23. static void process_DESC();
  24.  
  25. /* Here are a few necessary utilities */
  26.  
  27. static void put_name(world, name, size)
  28. WORLD *world;
  29. register char  *name;
  30. register int size;
  31. {
  32.     while (*name && size) {
  33.         fputc(*name++, world->inp);
  34.         size--;
  35.     }
  36.     while (size--) fputc(0, world->inp);    /* Pad the rest of the string w/ 0 */
  37. }
  38.  
  39. static void put_UBYTE(world, u)
  40. WORLD *world;
  41. UBYTE u;
  42. {
  43.     fputc((char)u, world->inp);
  44. }
  45.  
  46. static void put_UWORD(world, w)
  47. WORLD *world;
  48. UWORD w;
  49. {
  50.     put_UBYTE(world, (UBYTE)(w>>8));
  51.     put_UBYTE(world, (UBYTE)(w&0xFF));
  52. }
  53.  
  54. static void put_ULONG(world, l)
  55. WORLD *world;
  56. ULONG l;
  57. {
  58.     put_UWORD(world, (UWORD)(l>>16));
  59.     put_UWORD(world, (UWORD)(l&0xFFFF));
  60. }
  61.  
  62. static void put_FRACT(world, f)
  63. WORLD *world;
  64. double f;
  65. {
  66.     union {            /* Nasty... pass it a double, get it as a ULONG */
  67.         double f;
  68.         ULONG l;
  69.     } num;
  70.     num.f = f;
  71.     put_ULONG(world, num.l);
  72. }
  73.  
  74. static void put_XYZ(world, st)            /* Write a common string */
  75. WORLD *world;
  76. XYZ_st *st;
  77. {
  78.     put_FRACT(world, st->x);
  79.     put_FRACT(world, st->z);    /* Swap Y & Z for LightWave3D */
  80.     put_FRACT(world, st->y);
  81. }
  82.  
  83. static void put_RGB(world, st)            /* Write a common string */
  84. WORLD *world;
  85. RGB_st *st;
  86. {
  87.     put_UBYTE(world, 0);    /* PAD */
  88.     put_UBYTE(world, st->r);
  89.     put_UBYTE(world, st->g);
  90.     put_UBYTE(world, st->b);
  91. }
  92.  
  93. static void write_size(world, pos)
  94. WORLD *world;
  95. long pos;
  96. {
  97.     long size;
  98.     long cur = ftell(world->inp);
  99.     size = cur-pos;
  100.     if (size&1) { size++; put_UBYTE(world, (UBYTE)0); }
  101.     fseek(world->inp, pos-4L, 0);
  102.     put_ULONG(world, (ULONG)size);
  103.     fseek(world->inp, cur, 0);
  104. }
  105.  
  106. /********************/
  107. /* The MAIN section */
  108. /********************/
  109.  
  110. int write_LWOB(world, myfile)
  111. WORLD *world;
  112. FILE *myfile;
  113. {
  114.     long pos, pos2;
  115.     OBJECT *obj;
  116.  
  117.     if (!world || !myfile) return(0);
  118.     world->inp = myfile;
  119.  
  120.     /* Start the IFF TDDD file */
  121.     put_name(world, "FORM", 4);
  122.     put_ULONG(world, 0L);            /* Fill this in later [seek(,4L,0)] */
  123.     pos = ftell(world->inp);        /* Save where this starting position is */
  124.     put_name(world, "LWOB", 4);
  125.  
  126.     /* First, write *all* of the points in the entire object, up to 64K */
  127.     /* Swap the Y and Z values because of the changed axis orientation */
  128.     put_name(world, "PNTS", 4);
  129.     put_ULONG(world, 0L);
  130.     pos2 = ftell(world->inp);    /* Save for later */
  131.     for (obj=world->object; obj; obj=obj->next) {
  132.         dump_points(world, obj);
  133.     }
  134.     write_size(world, pos2);
  135.  
  136. /* All done.  Close up shop. */
  137.     write_size(world, pos);
  138.     fclose(world->inp);
  139.     return(1);
  140. }
  141.  
  142. void dump_points(world, object)
  143. WORLD *world;
  144. register OBJECT *object;
  145. {
  146.     register int i;
  147.     register XYZ_st *p;
  148.     OBJECT *obj;
  149.  
  150.     if (object->desc && object->desc->pcount) {
  151.         p = object->desc->pnts;
  152.         for (i=object->desc->pcount; i--; p++)
  153.             put_XYZ(world, p);
  154.     }
  155.  
  156.     /* Process children */
  157.     for (obj=object->child; obj; obj=obj->next)
  158.         dump_points(world, obj);
  159. }
  160.  
  161. static void process_INFO(world, info)
  162. WORLD *world;
  163. INFO *info;
  164. {
  165.     register ULONG i;
  166.     long pos;
  167.  
  168.     put_name(world, "INFO", 4);
  169.     put_ULONG(world, 0L);
  170.     pos = ftell(world->inp);    /* Save for later */
  171.  
  172.     for (i=0; i<8; i++)
  173.         if (info->brsh[i][0]) {
  174.             put_name(world, "BRSH", 4);
  175.             put_ULONG(world, 82L);
  176.             put_UWORD(world, (UWORD)i);
  177.             put_name(world, info->brsh[i], 80);
  178.         }
  179.  
  180.     for (i=0; i<8; i++)
  181.         if (info->stnc[i][0]) {
  182.             put_name(world, "STNC", 4);
  183.             put_ULONG(world, 82L);
  184.             put_UWORD(world, (UWORD)i);
  185.             put_name(world, info->stnc[i], 80);
  186.         }
  187.  
  188.     for (i=0; i<8; i++)
  189.         if (info->txtr[i][0]) {
  190.             put_name(world, "TXTR", 4);
  191.             put_ULONG(world, 82L);
  192.             put_UWORD(world, (UWORD)i);
  193.             put_name(world, info->txtr[i], 80);
  194.         }
  195.  
  196.     if (info->otrk[0]) {
  197.         put_name(world, "OTRK", 4);
  198.         put_ULONG(world, 18L);
  199.         put_name(world, info->otrk, 18);
  200.     }
  201.  
  202.     if (info->ambi) {
  203.         put_name(world, "AMBI", 4);
  204.         put_ULONG(world, 4L);
  205.         put_RGB(world, info->ambi);
  206.     }
  207.  
  208.     if (info->obsv) {
  209.         put_name(world, "OBSV", 4);
  210.         put_ULONG(world, 28L);
  211.         put_XYZ(world, &info->obsv->came);
  212.         put_XYZ(world, &info->obsv->rota);
  213.         put_FRACT(world, info->obsv->foca);
  214.     }
  215.  
  216.     if (info->ostr) {
  217.         put_name(world, "OSTR", 4);
  218.         put_ULONG(world, 56L);
  219.         put_name(world, info->ostr->path, 18);
  220.         put_XYZ(world, &info->ostr->tran);
  221.         put_XYZ(world, &info->ostr->rota);
  222.         put_XYZ(world, &info->ostr->scal);
  223.         put_UWORD(world, info->ostr->info);
  224.     }
  225.  
  226.     if (info->fade) {
  227.         put_name(world, "FADE", 4);
  228.         put_ULONG(world, 12L);
  229.         put_FRACT(world, info->fade->at);
  230.         put_FRACT(world, info->fade->by);
  231.         put_RGB(world, &info->fade->to);
  232.     }
  233.  
  234.     if (info->skyc) {
  235.         put_name(world, "SKYC", 4);
  236.         put_ULONG(world, 8L);
  237.         put_RGB(world, &info->skyc->hori);
  238.         put_RGB(world, &info->skyc->zeni);
  239.     }
  240.  
  241.     if (info->glb0) {
  242.         put_name(world, "GLB0", 4);
  243.         put_ULONG(world, 8L);
  244.         for (i=0; i<8; i++)
  245.             put_UBYTE(world, (UBYTE)info->glb0[i]);
  246.     }
  247.     write_size(world, pos);
  248. }
  249.  
  250. static void process_OBJ(world, obj)
  251. WORLD *world;
  252. OBJECT *obj;
  253. {
  254.     OBJECT *o;
  255.  
  256.     if (obj->extr) process_EXTR(world, obj);
  257.     else process_DESC(world, obj);
  258.  
  259.     for (o=obj->child; o; o=o->next)
  260.         process_OBJ(world, o);
  261.  
  262.     put_name(world, "TOBJ", 4);
  263.     put_ULONG(world, 0L);
  264. }
  265.  
  266. static void process_EXTR(world, obj)
  267. WORLD *world;
  268. OBJECT *obj;
  269. {
  270.     long pos;
  271.  
  272.     put_name(world, "EXTR", 4);
  273.     put_ULONG(world, 0L);
  274.     pos = ftell(world->inp);    /* Save for later */
  275.  
  276.     put_name(world, "LOAD", 4);
  277.     put_ULONG(world, 80L);
  278.     put_name(world, obj->extr->filename, 80);
  279.  
  280.     put_name(world, "MTRX", 4);
  281.     put_ULONG(world, 60L);
  282.     put_XYZ(world, &obj->extr->mtrx.tran);
  283.     put_XYZ(world, &obj->extr->mtrx.scal);
  284.     put_XYZ(world, &obj->extr->mtrx.rota1);
  285.     put_XYZ(world, &obj->extr->mtrx.rota2);
  286.     put_XYZ(world, &obj->extr->mtrx.rota3);
  287.  
  288.     write_size(world, pos);
  289. }
  290.  
  291. static void process_DESC(world, obj)
  292. WORLD *world;
  293. OBJECT *obj;
  294. {
  295.     register int i;
  296.     register DESC *desc;
  297.     FGRP *fgrp;
  298.     long pos;
  299.  
  300.     if (!obj) return;
  301.     desc = obj->desc;
  302.     if (!desc) return;
  303.  
  304.     put_name(world, "DESC", 4);
  305.     put_ULONG(world, 0L);
  306.     pos = ftell(world->inp);    /* Save for later */
  307.  
  308.     if (desc->name) {
  309.         put_name(world, "NAME", 4);
  310.         put_ULONG(world, 18L);
  311.         put_name(world, desc->name, 18);
  312.     }
  313.  
  314.     if (desc->posi) {
  315.         put_name(world, "POSI", 4);
  316.         put_ULONG(world, 12L);
  317.         put_XYZ(world, desc->posi);
  318.     }
  319.  
  320.     if (desc->size) {
  321.         put_name(world, "SIZE", 4);
  322.         put_ULONG(world, 12L);
  323.         put_XYZ(world, desc->size);
  324.     }
  325.  
  326.     if (desc->colr) {
  327.         put_name(world, "COLR", 4);
  328.         put_ULONG(world, 4L);
  329.         put_RGB(world, desc->colr);
  330.     }
  331.  
  332.     if (desc->refl) {
  333.         put_name(world, "REFL", 4);
  334.         put_ULONG(world, 4L);
  335.         put_RGB(world, desc->refl);
  336.     }
  337.  
  338.     if (desc->tran) {
  339.         put_name(world, "TRAN", 4);
  340.         put_ULONG(world, 4L);
  341.         put_RGB(world, desc->tran);
  342.     }
  343.  
  344.     if (desc->spc1) {
  345.         put_name(world, "SPC1", 4);
  346.         put_ULONG(world, 4L);
  347.         put_RGB(world, desc->spc1);
  348.     }
  349.  
  350.     if (desc->ints) {
  351.         put_name(world, "INTS", 4);
  352.         put_ULONG(world, 4L);
  353.         put_FRACT(world, (*desc->ints));
  354.     }
  355.  
  356.     /* Mandatory field... stuff it, regardless */
  357.     if (desc->shap) {
  358.         put_name(world, "SHAP", 4);
  359.         put_ULONG(world, 4L);
  360.         put_UWORD(world, (UWORD)desc->shap[0]);
  361.         put_UWORD(world, (UWORD)desc->shap[1]);
  362.     } else {
  363.         put_name(world, "SHAP", 4);
  364.         put_ULONG(world, 4L);
  365.         put_UWORD(world, (UWORD)2);
  366.         put_UWORD(world, (UWORD)1);
  367.     }
  368.  
  369.     if (desc->axis) {
  370.         put_name(world, "AXIS", 4);
  371.         put_ULONG(world, 36L);
  372.         put_XYZ(world, &desc->axis->xaxi);
  373.         put_XYZ(world, &desc->axis->yaxi);
  374.         put_XYZ(world, &desc->axis->zaxi);
  375.     }
  376.  
  377.     if (desc->tpar) {
  378.         put_name(world, "TPAR", 4);
  379.         put_ULONG(world, 64L);
  380.         for (i=0; i<16; i++) put_FRACT(world, desc->tpar[i]);
  381.     }
  382.  
  383.     if (desc->surf) {
  384.         put_name(world, "SURF", 4);
  385.         put_ULONG(world, 5L);
  386.         for (i=0; i<5; i++) put_UBYTE(world, desc->surf[i]);
  387.         put_UBYTE(world, (UBYTE)0);    /* To make this chunk even-sized */
  388.     }
  389.  
  390.     if (desc->mttr) {
  391.         put_name(world, "MTTR", 4);
  392.         put_ULONG(world, 2L);
  393.         put_UBYTE(world, desc->mttr->type);
  394.         put_UBYTE(world, (UBYTE)(((int)((desc->mttr->indx-1.0)*100.0))&0xFF));
  395.     }
  396.  
  397.     if (desc->spec) {
  398.         put_name(world, "SPEC", 4);
  399.         put_ULONG(world, 2L);
  400.         put_UBYTE(world, desc->spec[0]);
  401.         put_UBYTE(world, desc->spec[1]);
  402.     }
  403.  
  404.     if (desc->prp0) {
  405.         put_name(world, "PRP0", 4);
  406.         put_ULONG(world, 6L);
  407.         for (i=0; i<6; i++) put_UBYTE(world, desc->prp0[i]);
  408.     }
  409.  
  410.     if (desc->prp1) {
  411.         put_name(world, "PRP1", 4);
  412.         put_ULONG(world, 8L);
  413.         for (i=0; i<8; i++) put_UBYTE(world, desc->prp1[i]);
  414.     }
  415.  
  416.     if (desc->stry) {
  417.         put_name(world, "STRY", 4);
  418.         put_ULONG(world, 56L);
  419.         put_name(world, desc->stry->path, 18);
  420.         put_XYZ(world, &desc->stry->tran);
  421.         put_XYZ(world, &desc->stry->rota);
  422.         put_XYZ(world, &desc->stry->scal);
  423.         put_UWORD(world, desc->stry->info);
  424.     }
  425.  
  426.     if (desc->pcount) {
  427.         put_name(world, "PNTS", 4);
  428.         put_ULONG(world, (ULONG)desc->pcount*12L+2L);
  429.         put_UWORD(world, desc->pcount);
  430.         for (i=0; i<desc->pcount; i++)
  431.             put_XYZ(world, &desc->pnts[i]);
  432.     }
  433.  
  434.     if (desc->ecount) {
  435.         put_name(world, "EDGE", 4);
  436.         put_ULONG(world, (ULONG)desc->ecount*4L+2L);
  437.         put_UWORD(world, desc->ecount);
  438.         for (i=0; i<2*desc->ecount; i++)
  439.             put_UWORD(world, desc->edge[i]);
  440.     }
  441.  
  442.     if (desc->eflg) {
  443.         put_name(world, "EFLG", 4);
  444.         put_ULONG(world, (ULONG)desc->eflg->num+2L);
  445.         put_UWORD(world, desc->eflg->num);
  446.         for (i=0; i<desc->eflg->num; i++)
  447.             put_UBYTE(world, desc->eflg->eflg[i]);
  448.         if (desc->eflg->num&1) put_UBYTE(world, 0);    /* Pad on even boundary */
  449.     }
  450.  
  451.     if (desc->fcount) {
  452.         put_name(world, "FACE", 4);
  453.         put_ULONG(world, (ULONG)desc->fcount*6L+2L);
  454.         put_UWORD(world, desc->fcount);
  455.         for (i=0; i<3*desc->fcount; i++)
  456.             put_UWORD(world, desc->face[i]);
  457.  
  458.         if (desc->clst) {
  459.             put_name(world, "CLST", 4);
  460.             put_ULONG(world, (ULONG)desc->fcount*3L+2L);
  461.             put_UWORD(world, desc->fcount);
  462.             for (i=0; i<3*desc->fcount; i++)
  463.                 put_UBYTE(world, desc->clst[i]);
  464.             if (desc->fcount&1) put_UBYTE(world, 0);    /* Pad to even length */
  465.         }
  466.         if (desc->rlst) {
  467.             put_name(world, "RLST", 4);
  468.             put_ULONG(world, (ULONG)desc->fcount*3L+2L);
  469.             put_UWORD(world, desc->fcount);
  470.             for (i=0; i<3*desc->fcount; i++)
  471.                 put_UBYTE(world, desc->rlst[i]);
  472.             if (desc->fcount&1) put_UBYTE(world, 0);    /* Pad to even length */
  473.         }
  474.         if (desc->tlst) {
  475.             put_name(world, "TLST", 4);
  476.             put_ULONG(world, (ULONG)desc->fcount*3L+2L);
  477.             put_UWORD(world, desc->fcount);
  478.             for (i=0; i<3*desc->fcount; i++)
  479.                 put_UBYTE(world, desc->tlst[i]);
  480.             if (desc->fcount&1) put_UBYTE(world, 0);    /* Pad to even length */
  481.         }
  482.     }
  483.  
  484.     for (fgrp=desc->fgrp; fgrp; fgrp=fgrp->next) {
  485.         put_name(world, "FGRP", 4);
  486.         put_ULONG(world, (ULONG)fgrp->num*2L+2L+18L);
  487.         put_UWORD(world, fgrp->num);
  488.         put_name(world, fgrp->name, 18);
  489.         for (i=0; i<fgrp->num; i++)
  490.             put_UWORD(world, fgrp->face[i]);
  491.     }
  492.     write_size(world, pos);
  493. }
  494.  
  495.